<?php

namespace privateClass\App;

class Data {
	
	/**
	 *
	 * @param unknown $_query_string
	 * @param unknown $_conf
	 * @return mixed
	 */
	public static function fetch($_query_string, $_conf) {
		$result = FALSE;
		
		$_cookie_file = self::init_cookie($_query_string['query_uri'],$_conf['app_id']);
		$_header = self::init_header($_query_string['method'], $_conf['config']);
		$_request = self::init_request($_query_string['method'],$_conf['config']);

		$_result = (!empty($_query_string['query_uri'])) ?
			_curl($_query_string['query_uri'], $_request, $_query_string['method'], $_conf['config']['query']['settings']['timeout'], TRUE, $_header, $_conf['config']['query']['settings']['follow_location'], $_conf['config']['query']['custom']['referer'], $_conf['config']['query']['custom']['user_agent'], FALSE, TRUE, $_cookie_file) : 
			['response'=>FALSE, 'status_code'=>0];
		
		if ($_result['response'] != FALSE) {//处理response-header
			//$_result['response_header'] = self::parse_header($_result['response']);
			$_tmp_result = explode("\r\n\r\n", $_result['response'],2);
			$_result['response_header'] = $_tmp_result[0];
			$_result['response'] = $_tmp_result[1];
			
		}
		
		preg_match('/charset=(.*)/', $_result['response_header'], $match);
		
		$_result['charset'] = (isset($match[1]) && !empty($match[1])) ? $match[1] : 'utf-8';
		
		
		return array_merge(['request'=>$_request], $_result);
	}
	
	
	/**
	 *
	 * @param unknown $contents
	 * @param unknown $_conf
	 * @return mixed
	 */
	public static function get_stream($contents, $_conf) {
		$_result = ['content_type'=>$_conf['query']['custom']['content_type'],'content'=>$contents];
		return $_result;
	}
	
	/**
	 *
	 * @param unknown $contents
	 * @param unknown $_conf
	 * @return mixed
	 */
	public static function get_vars($contents, $_conf, $charset = 'utf-8') {
		$result = FALSE;
		
		switch ($_conf['data_type']) {
			case 'xml' : 
				$result = xml_to_array($contents, 1);
				break;
			case 'json' :
				$result = json_decode($contents, TRUE);
				break;
			case 'msgpack' :
				$result = msgpack_unpack($contents);
				break;
			case 'html' :
			default:
				$contents = str_get_html($contents);
				$result = self::recursion_vars($contents, $_conf['vars'], $charset);
				//$result = self::get_vars_of_html($contents, $_conf, $charset);
				break;
		}
		
		return $result;
	}
	
	private static function recursion_vars($contents, $_conf, $charset) {
		$result = [];
		foreach ($_conf as $k => $v) {
			if  (is_array($v)) $result = array_merge($result, [$k=>self::recursion_vars($contents, $v, $charset)]);
			else $result = array_merge($result, [$k=>self::get_vars_of_html($contents, $v, $charset)]);
		}
		
		
		return $result;
	}
	
	private static function get_vars_of_html($contents, $_conf, $charset = 'utf-8') {
		$result = FALSE;
		//$html_handler = str_get_html($contents);
		$html_handler = $contents;
		
		//foreach ($_conf['vars'] as $k=>$v) {
			$_matches = NULL;
			$tmp_result = NULL;
				
				
			//匹配静态变量值
			if (self::match_static_value_prefix('value::', $_conf, $_matches)) {
		
				$tmp_result = $_matches[1];
		
		
		
			} elseif (preg_match_all('/(.+?):(eq|lt|gt|btw|first|last)\S*|([^:]+)|(.+?)\S*/', $_conf, $_matches, PREG_SET_ORDER) && $_matches) {
				//加入jquery伪类访问方法 2012-12-25
		
				$tmp_node = NULL;
				!empty($_matches) ? $tmp_node = $html_handler : FALSE;
				foreach ($_matches as $_match) {
					//if $_matches.length == 3 含有高级选择器
					//if $_matches.length == 4 无高级选择器
					$_match_count = count($_match);
					$tmp_match = [];
					
					if (is_a($tmp_node,'simple_html_dom')) $tmp_node = [$tmp_node];
					if ($_match_count == 4) {
						$result_node = [];
						
						
						foreach ($tmp_node as $node) {
							$find = method_exists($node, 'find') ? $node->find($_match[0]) : FALSE;
							(!empty($find) && $find != FALSE) ? $result_node = array_merge($result_node, $find) : FALSE;
						}
						$tmp_node = !empty($result_node) ? $result_node : NULL;
					} elseif ($_match_count == 3) {
						preg_match_all('/:(first|last|(eq|gt|lt|btw)\((-?\d{1,})\))/', $_match[0], $tmp_match, PREG_SET_ORDER);
						//首先确定上级元素内容 然后从上级元素内容中获取本级元素伪类选择器内容
						if (preg_match('/(.+)(\s.*):/', $_match[0], $_prev_match) > 0) {
							
							$prev_find = method_exists($tmp_node[0], 'find') ? $tmp_node[0]->find($_prev_match[1]) : FALSE;
							$_match[1] = $_prev_match[2];
							
						} else $prev_find = $tmp_node;
						$result_node = [];
						
						if (count($prev_find) > 0 && isset($prev_find[0])) foreach ($prev_find as $the_find) {
							$find = FALSE;
							
							foreach ($tmp_match as $_cell_match) {

								
								if (isset($_cell_match[2])) {//匹配结果为后项(eq|gt|lt|btw)的情况
									
									if ($_match[1] == ' ') {
										//foreach ($tmp_node as $node) {
											$find = method_exists($the_find, 'children') ? $the_find->children() : FALSE;
											//(!empty($find) && $find != FALSE) ? $result_node = array_merge($result_node, $find) : FALSE;
										//}
									} else {
							
										//foreach ($tmp_node as $node) {
											$find = method_exists($the_find, 'find') ? $the_find->find($_match[1]) : FALSE;
											//(!empty($find) && $find != FALSE) ? $result_node = array_merge($result_node, $find) : FALSE;
										//}
							
									}
										
									switch($_cell_match[2]) {
										case 'eq' :
											$find = [isset($find[$_cell_match[3]]) ? $find[$_cell_match[3]] : FALSE];
											break;
										case 'gt' :
											$find = self::gt($find, $_cell_match[3]);
											break;
										case 'lt' :
											$find = self::lt($find, $_cell_match[3]);
											break;
										case 'btw' :
											$_gl = explode(',',$_cell_match[3]);
											$find = self::btw($find, $_gl[0], $_gl[1]);
											break;
										default :
											$find = FALSE;
											break;
									}
									
								} elseif (!isset($_cell_match[2])) {//匹配结果为前项(first|last)的情况
									if ($_cell_match[1] == 'first') {
										if (method_exists($tmp_node, 'firstChild')) {
											$find = ($_cell_match[1] == ' ' || empty($_cell_match[1])) ? $tmp_node->firstChild() : $tmp_node->find($_match[1])->firstChild() ;
										} else $find = FALSE;
									} elseif ($_cell_match[1] == 'last') {
										if (method_exists($tmp_node, 'firstChild')) {
											$find = ($_cell_match[1] == ' ' || empty($_cell_match[1])) ? $tmp_node->lastChild() : $tmp_node->find($_match[1])->lastChild() ;
										} else $find = FALSE;
									}
								}
								
								(!empty($find) && $find != FALSE) ? $result_node = array_merge($result_node, $find) : FALSE;
							}
							
							
							
						}
						$tmp_node = !empty($result_node) ? $result_node : NULL;
					}
				}
				
				
				
				//将计算出来的tmp_node封装为array
				if (is_a($tmp_node, 'simple_html_dom_node')) {
					$tmp_attr = [];
					if (isset($tmp_node->attr) && !empty($tmp_node->attr) && count($tmp_node->attr) > 0) foreach ($tmp_node->attr as $attr_k => $v) {
						$tmp_attr[$attr_k] = self::transcoding($v,'utf-8', $charset);
					} else $tmp_attr = [];
					$tmp_result = [
						'value'	=>	self::transcoding($tmp_node->innertext,'utf-8', $charset),
						'attribute'	=>	$tmp_attr
					];
				} elseif (count($tmp_node) == 1) {
					$tmp_attr = [];
					if (isset($tmp_node[0]->attr) && !empty($tmp_node[0]->attr) && count($tmp_node[0]->attr) > 0) foreach ($tmp_node[0]->attr as $attr_k => $v) {
						$tmp_attr[$attr_k] = self::transcoding($v,'utf-8', $charset);
					} else $tmp_attr = [];
					$tmp_result = [
						'value'	=>	self::transcoding($tmp_node[0]->innertext,'utf-8', $charset),
						'attribute'	=>	$tmp_attr
					];
				} elseif ($tmp_node == NULL) {
					$tmp_result = [
						'value'	=>	'',
						'attribute'	=>	[]
					];
						
				} else {
					foreach ($tmp_node as $i => $node) {
						$tmp_attr = [];
						if (isset($node->attr) && !empty($node->attr) && count($node->attr) > 0) foreach ($node->attr as $attr_k => $v) {
							$tmp_attr[$attr_k] = self::transcoding($v,'utf-8', $charset);
						} else $tmp_attr = NULL;
						$tmp_result[$i] = [
							'value'	=>	self::transcoding($node->innertext,'utf-8', $charset),
							'attribute'	=>	$tmp_attr
						];
					}
				}
		
		
		
			} else {
				//按照一般方法查找元素
		
				$tmp_node = $html_handler->find($v);
				
				if (isset($tmp_node[0]) && count($tmp_node) == 1) {
					$tmp_attr = [];
					if (count($tmp_node[0]->attr) > 0) foreach ($tmp_node[0]->attr as $v) {
						$tmp_attr[] = self::transcoding($v,'utf-8', $charset);
					}
					$tmp_result = [
						'value'	=>	self::transcoding($tmp_node[0]->innertext,'utf-8', $charset),
						'attribute'	=>	$tmp_attr
					];
				}
				elseif (isset($tmp_node[0]) && count($tmp_node) > 1) foreach($tmp_node as $n) {
					$tmp_attr = [];
					if (count($n->attr) > 0) foreach ($n->attr as $v) {
						$tmp_attr[] = self::transcoding($v,'utf-8', $charset);
					}
					$tmp_result[] = [
						'value'	=>	self::transcoding($n->innertext,'utf-8', $charset),
						'attribute'	=>	$tmp_attr
					];
				}
				else $tmp_result = [
					'value'	=>	'',
					'attribute'	=>	[]
				];
		
		
		
			}
			$result = $tmp_result;
			//$result[$k] = $tmp_result;
		//}
		return $result;
	}
	
	/**
	 * 
	 * @param unknown $_string
	 * @param string $_to
	 * @param string $_from
	 * @return string
	 */
	private static function transcoding ($_string, $_to = 'utf-8', $_from = 'utf-8') {
		$_result = '';
		$_from = strtolower(trim($_from));
		if ($_from != 'utf-8') {
			$_result = (!empty($_string)) ? mb_convert_encoding($_string, $_to, $_from) : '';
		} else $_result = $_string;
		return $_result;
	}
	
	/**
	 * 
	 * @param unknown $pattern
	 * @param unknown $subject
	 * @param unknown $_match
	 * @return boolean
	 */
	private static function match_static_value_prefix ($pattern, $subject, &$_match) {
		$result = FALSE;
		$_match = explode($pattern, $subject, 2);
		if (count($_match) == 2) $result = TRUE;
		return $result;
	}
	
	//add jquery style Pseudo-classes selector
	/**
	 * 
	 * @param string $selector
	 * @param string $idx
	 * @return multitype:
	 */
	private static function lt($selector = NULL, $idx = NULL) {
		//$node = ($selector == 'children') ? $this->children() : $this->find($selector);
		$_cel_idx = NULL;
		if ($idx != NULL) {
			$_cel_idx = count($selector) - $idx - 1;
			$_cel_idx = $_cel_idx < 0 ? NULL : 0 - $_cel_idx;
		}
	
		return array_slice($selector, 0, $_cel_idx);
	}
	
	
	/**
	 * 
	 * @param string $selector
	 * @param number $idx
	 * @return multitype:
	 */
	private static function gt($selector = NULL, $idx = 0) {
		//$node = ($selector == 'children') ? $this->children() : $this->find($selector);
		$_cel_idx = 0;
		if ($idx != 0) {
			$_cel_idx = $idx;
			$_cel_idx > count($selector) ? $_cel_idx = 0 : FALSE;
		}
	
		return array_slice($selector, $_cel_idx, NULL);
	}
	
	
	/**
	 * 
	 * @param string $selector
	 * @param number $gidx
	 * @param string $lidx
	 * @return multitype:
	 */
	private static function btw($selector = NULL, $gidx = 0, $lidx = NULL) {
		//$node = ($selector == 'children') ? $this->children() : $this->find($selector);
		
		$_cel_lidx = NULL;
		$_cel_gidx = 0;
		if ($gidx <= $lidx) {
			if ($lidx != NULL) {
				$_cel_lidx = count($selector) - $lidx - 1;
				$_cel_lidx = $_cel_lidx < 0 ? NULL : 0 - $_cel_lidx;
			}
		
			
			if ($gidx != 0) {
				$_cel_gidx = $gidx;
				$_cel_gidx > count($selector) ? $_cel_gidx = 0 : FALSE;
			}
		}
		return array_slice($selector, $_cel_gidx, $_cel_lidx);
	}	
	
	/**
	 * 
	 * @param unknown $uri
	 * @return mixed
	 */
	public static function get_domain($uri) {
		return parse_url($uri,PHP_URL_HOST);
	}
	
	
	/**
	 * 
	 * @param unknown $_raw_http_response
	 * @return multitype:
	 */
	private static function parse_header($_raw_http_response) {
		return explode("\r\n\r\n",$_raw_http_response,2)[0];
	}
	
	
	/**
	 * 
	 * @param unknown $_http_header
	 * @return Ambigous <>
	 */
	public static function parse_cookie($_http_header) {
		$matches_cookie = [];
		preg_match_all( '/Set-Cookie: (.+?);\s/', $_http_header, $matches_cookie);
		return $matches_cookie[1];
	}
	
	/**
	 * 初始化请求header
	 * @param string $_request_type
	 * @param unknown $_conf
	 * @return multitype:string
	 */
	private static function init_header($_request_type = _HTTP_GET, $_conf) {
		$_header = [];
		if ($_request_type != _HTTP_GET && !empty($_conf['query']['settings']['enctype'])) $_header[] = 'Content-Type: '.$_conf['query']['settings']['enctype'];
		return array_merge($_header,$_conf['query']['custom']['header']);
	}
	
	/**
	 * 初始化请求内容
	 * @param string $_request_type
	 * @param unknown $_conf
	 * @return Ambigous <string, mixed>
	 */
	private static function init_request($_request_type = _HTTP_GET, $_conf) {
		$_request = '';
		if ($_request_type != _HTTP_GET) {
			//转换request中文编码
			if (isset($_POST) && count($_POST) > 0 && strtolower(trim($_conf['query']['custom']['charset'])) != 'utf-8') {
				foreach ($_POST as $k => $v) {
					$_POST[$k] = iconv('utf-8',$_conf['query']['custom']['charset'].'//IGNORE',urldecode($v));
				}
			}
			
			
			
			$_request = (isset($_POST) && count($_POST) > 0) ? http_build_query($_POST) : '';
			
			//检测是否启用了use_raw_post_string选项
			if ($_conf['query']['settings']['use_raw_post_string'] == TRUE) $_request = file_get_contents('php://input');
			//转换params 主要解决php请求变量中 . => _ 的情况
			if (isset($_conf['query']['custom']['transparams'])) $_request = self::transform_params($_request, $_conf['query']['custom']['transparams']);
			
		}
		return $_request;
	}
	
	
	/**
	 * 初始化cookie
	 * @param string $_uri
	 * @return string
	 */
	private static function init_cookie($_uri = '', $app_id = 'no-appid') {
		file_exists(COOKIE_CACHE_PATH.$app_id) ? TRUE : mkdir(COOKIE_CACHE_PATH.$app_id, 0777);

		return COOKIE_CACHE_PATH.$app_id.DIRECTORY_SEPARATOR.\Yaf\Registry::get('AMSCID').'.cookie';
	}
	
	private static function transform_params($_param_string, $_transform_params_conf) {
		foreach ($_transform_params_conf as $find => $replace) {
			$_param_string = str_replace($find.'=', $replace.'=', $_param_string);
		}
		return $_param_string;
	}
	
	private static function implode_cookie($cookie) {
		$tmp = [];
		foreach ($cookie as $n => $line) {
			$tmp[] = $n.'='.$line;
		}
		return implode(';', $tmp);
	}
	
	private static function explode_cookie($cookie) {
		$result = [];
		foreach ($cookie as $line) {
			if (!strpos($line, '=')) break;
			$tmp = explode('=', $line, 2);
			$result[$tmp[0]] = $tmp[1];
		}
		return $result;
	}
}

?>